package com.grupobbva.iici.dao.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.grupobbva.iici.dao.BaseDAO;
import com.grupobbva.iici.serializable.BaseDomain;
import com.grupobbva.iici.util.FiltroDTO;
import com.grupobbva.iici.util.ParametroDTO;

public abstract class BaseDAOImpl extends HibernateDaoSupport implements BaseDAO, Serializable {

	private static final long serialVersionUID = 1L;

	private static Logger log = Logger.getLogger(BaseDAOImpl.class);

	protected void escribirParametros(String metodo, Object... parametros) {
		try {
			if (parametros == null) {
				log.info(metodo + " SIN PARAMETROS");
				return;
			}
			for (int i = 0; i < parametros.length; i++) {
				log.info(metodo + " PARAMETRO " + (i + 1) + "[" + BeanUtils.describe(parametros[i]) + "]");
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}

	@Autowired
	public void init(SessionFactory sessionFactory) {
		setSessionFactory(sessionFactory);
	}

	public BaseDomain registrar(BaseDomain entidad) {
//		escribirParametros("registrar", entidad);
		getHibernateTemplate().save(entidad);
		getHibernateTemplate().flush();
		return entidad;
	}

	public List registrarTodo(List lstEntidad) {
//		escribirParametros("registrarTodo", lstEntidad);
		getHibernateTemplate().saveOrUpdateAll(lstEntidad);
		getHibernateTemplate().flush();
		return lstEntidad;
	}

	public BaseDomain modificar(BaseDomain entidad) {
		escribirParametros("modificar", entidad);
		getHibernateTemplate().merge(entidad);
		return entidad;
	}

	public BaseDomain eliminar(BaseDomain entidad) {
		escribirParametros("eliminar", entidad);
		getHibernateTemplate().delete(entidad);
		return entidad;
	}

	public <T> T obtenerEntidadPorCodigo(Class<T> clase, Object codigo) {
		escribirParametros("obtenerEntidadPorCodigo " + clase.getName(), codigo);
		return getHibernateTemplate().get(clase, (Serializable) codigo);
	}

	public List obtenerEntidadesPorFiltros(Class clase, FiltroDTO filtroDTO, int... indicadorInicioCantidad) {
		log.info("Inicio de Consulta :"+clase);
		Criteria criteria = getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(clase);
		if(filtroDTO!=null){
		Collection<String> values=filtroDTO.getAliasDTO().values();
		for(String alias:values){
			criteria=criteria.createAlias(alias, alias);			
		}
		log.info("SET PARAMETERS");
		
			for (ParametroDTO parametroDTO : filtroDTO.getFiltro()) {
				if (parametroDTO.getValorParametro() == null || parametroDTO.getValorParametro().equals("")) {
					log.info("PARAMETRO EXCLUIDO: " + parametroDTO.getNombreParametro() + " : " + parametroDTO.getValorParametro());
					continue;
				}
				log.info("PARAMETRO INCLUIDO: " + parametroDTO.getNombreParametro() + " : " + parametroDTO.getValorParametro());
				if (parametroDTO.getTipoParametro().equals(ParametroDTO.TIPO_IGUAL)) {
					criteria.add(Restrictions.eq(parametroDTO.getNombreParametro(), parametroDTO.getValorParametro()));
				} else if (parametroDTO.getTipoParametro().equals(ParametroDTO.TIPO_LIKE)) {
					criteria.add(Restrictions.like(parametroDTO.getNombreParametro(), "%" + parametroDTO.getValorParametro() + "%"));
				}
			}
	
			log.info("FIN SET PARAMETERS");
			log.info("SET PARAMETERS LIKE");
			for (ParametroDTO parametroDTO : filtroDTO.getOrdenamiento()) {
				if (parametroDTO.getOrdenamiento().equals(ParametroDTO.ORDEN_ASCENDENTE)) {
					log.info("PARAMETRO : " + parametroDTO.getNombreParametro() + " : ASC ");
					criteria.addOrder(Order.asc(parametroDTO.getNombreParametro()));
				} else {
					log.info("PARAMETRO : " + parametroDTO.getNombreParametro() + " : DESC ");
					criteria.addOrder(Order.desc(parametroDTO.getNombreParametro()));
				}
			}
		}
		log.info("FIN SET PARAMETERS LIKE");
		log.info("Inicio de Consulta :"+clase);
		return criteria.list();
	}

	public <T> T obtenerEntidadPorFiltros(Class clase, FiltroDTO filtroDTO) {
		// escribirParametros("obtenerEntidadPorFiltros "+clase.getName(),filtroDTO);
		List lista = obtenerEntidadesPorFiltros(clase, filtroDTO);
		if (lista.size() > 0) {
			return (T) lista.get(0);
		}
		return null;
	}



}